<?php
namespace Lib\Db;

use \PDO;
use \Lib;

class PdoDB extends PDO {
    private $db;
    private $error;
    private $stmt;

    public function __construct() {
        $this->connect();
    }

    public function connect() {
        $res     = Lib\Conf::get("database.master");
        $table   = $res['jack_meal'];
        $dsn     = 'mysql:host=' . $table['hostname'] . ';dbname=' . $table['database'];
        $options = array(
            PDO::ATTR_PERSISTENT         => true,
            PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
            PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
        );
        try {
            $this->db = new PDO($dsn, $table['username'], $table['password'], $options);
        } catch (PDOException $e) {
            $this->error = $e->getMessage();
        }
    }

    // 预处理
    public function prepare($sql) {
        $this->stmt = $this->db->prepare($sql);
    }

    // 绑定value
    public function bind($param, $value, $type = null) {
        if (is_null($type)) {
            switch (true) {
                case is_int($value):
                    $type = PDO::PARAM_INT;
                    break;
                case is_bool($value):
                    $type = PDO::PARAM_BOOL;
                    break;
                case is_null($value):
                    $type = PDO::PARAM_NULL;
                    break;
                default:
                    $type = PDO::PARAM_STR;
            }
        }
        $this->stmt->bindValue($param, $value, $type);
    }

    // 绑定数组
    public function bindArray($array) {
        foreach ($array as $key => $value) {
            $this->bind($key, $value);
        }
    }

    // 执行sql
    public function execute($params = []) {
        if (!empty($params)) {
            return $this->stmt->execute($params);
        }

        return $this->stmt->execute();
    }

    // 查询返回多条记录
    public function results() {
        $this->execute();

        return $this->stmt->fetchAll(PDO::FETCH_ASSOC);
    }

    // 执行返回一行记录
    public function single() {
        $this->execute();

        return $this->stmt->fetch(PDO::FETCH_ASSOC);
    }

    // 执行结果行数 affected by a DELETE, INSERT, or UPDATE statement.
    public function rowCount() {
        return $this->stmt->rowCount();
    }

    // 结果行数 affected by a SELECT statement.
    public function fetchColumn() {
        return $this->stmt->fetchColumn();
    }

    // 最后一次插入的ID
    public function lastInsertId() {
        return $this->db->lastInsertId();
    }

    // 事务开始
    public function beginTransaction() {
        return $this->db->beginTransaction();
    }

    // 事务提交
    public function commit() {
        return $this->db->commit();
    }

    // 事务回滚
    public function rollBack() {
        return $this->db->rollBack();
    }

    // 插入记录
    public function insertRow($data) {
        $ret = 0;
        if (empty($data)) {
            return $ret;
        }
        $sql = "INSERT INTO " . $this->getTableName() . "(";

        $params = $paramsKeys = [];
        foreach ($data as $key => $val) {
            $columns[]        = $key;
            $tmpSign          = ":" . $key;
            $paramsKeys[]     = $tmpSign;
            $values[]         = "'" . $this->addsla($val) . "'";
            $params[$tmpSign] = $val;

        }
        $sql .= implode(",", $columns) . ") VALUES (";
        $sql .= implode(",", $paramsKeys) . ")";

        $this->prepare($sql);
        $this->bindArray($params);
        $rs = $this->execute();
        if ($rs) {
            $ret = $this->lastInsertId();
        }

        return $ret;
    }

    // 修改条件处理
    public function opFields($data, $judge = '=', $preSign = 'f_') {
        $sql     = ' ';
        $mapData = [];
        foreach ($data as $key => $val) {
            $mapIndex           = ':' . $preSign . $key;
            $sql                .= '`' . $key . '`' . $judge . $mapIndex . ',';
            $mapData[$mapIndex] = $val;
        }

        if (!empty($sql)) {
            $sql = rtrim($sql, ',');
        }

        return [
            'sql'     => $sql,
            'mapData' => $mapData,
        ];
    }


    // where 条件
    public function opCondition($condition) {
        $sql     = ' WHERE ';
        $mapData = [];
        $preSign = 'w_';
        if (is_string($condition)) {
            return [
                'sql'     => $sql . $condition,
                'mapData' => $mapData,
            ];
        } else {
            foreach ($condition as $key => $item) {
                $mapIndex = ':' . $preSign . $item['filed'];

                $sign = isset($sign) ? $sign : "=";
                if ($key) {
                    $sql .= ' ' . $item['connect'] . ' `' . $item['filed'] . '`' . $sign . $mapIndex;
                } else {
                    $sql .= ' `' . $item['filed'] . '`' . $sign . $mapIndex;
                }

                $mapData[$mapIndex] = $item['data'];
            }
        }

        return [
            'sql'     => $sql,
            'mapData' => $mapData,
        ];
    }

    /**
     * 修改
     * [
     * [
     * 'filed' => 'id',
     * 'data'  => '1',
     * 'sign'  => '=',
     * ],]
     */
    public function edit($where, $data) {
        $sql       = 'UPDATE ' . $this->getTableName() . ' SET';
        $filesData = $this->opFields($data);

        $whereData = $this->opCondition($where);

        $sql       .= $filesData['sql'] . $whereData['sql'];
        $dataValue = array_merge($filesData['mapData'], $whereData['mapData']);
        $this->prepare($sql, PDO::CURSOR_FWDONLY);
        $updateFlag = $this->execute($dataValue);

        return $updateFlag ? $this->rowCount() : 0;
    }

    /**
     * 删除
     */
    public function delete($where) {
        $sql = 'DELETE FROM ' . $this->getTableName();

        $whereStr = ' WHERE 1 ';
        foreach ($where as $key => $value) {
            $whereStr .= " AND $key = '$value'";
        }

        $sql .= $whereStr;

        return $this->db->exec($sql);
    }
}

?>
